package com.zetatech.bdp.writer.utils;

import com.zaxxer.hikari.HikariDataSource;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author cheng.cao@zetatech.com.cn
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DataSourceHolder {
    private Map<String, DataSource> holder = new ConcurrentHashMap<>();
    private AtomicBoolean bindHook = new AtomicBoolean(false);

    public DataSource getDataSource(String url, String driver, String username, String password) {
        String key = url + "_" + driver;
        DataSource returnDs = holder.get(key);
        if (returnDs == null) {
            synchronized (holder) {
                if (returnDs == null) {
                    HikariDataSource ds = new HikariDataSource();
                    ds.setJdbcUrl(url);
                    ds.setDriverClassName(driver);
                    ds.setUsername(username);
                    ds.setPassword(password);
                    holder.put(key, ds);
                    if (bindHook.compareAndSet(false,true)) {
                        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                            @Override
                            public void run() {
                                log.info("清理数据库连接池:连接池个数：{}", holder.size());
                                for (DataSource source : holder.values()) {
                                    try {
                                        ((HikariDataSource) source).close();
                                    } catch (Exception e) {
                                    }
                                }
                            }
                        }));
                    }
                    returnDs = ds;
                }
            }
        }
        return returnDs;
    }

    private static class Holder {
        private static DataSourceHolder instance = new DataSourceHolder();
    }

    public static DataSourceHolder me() {
        return Holder.instance;
    }
}
